﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.IO;
using System.Xml.Serialization;
[assembly: CLSCompliant(true)]
namespace Bxas.Core
{
    [Serializable]
    public class ColumnInfo : StandardProperties
    {
        public String priymatyKeyColumnName;
        public Type priymatyKeyColumnType;
        public String TableName;
        public Dictionary<String, Boolean> IsUpdateOrInsert = new Dictionary<string, bool>();

        #region Get Fields
        public object[,] GetFields(Type t)
        {

            PropertyInfo[] fields = t.GetProperties();
            PropertyInfo field;
            Attribute[] attributes;
            object[,] structureInfo = new object[fields.Length, 2];
            try
            {
                for (int i = 0; i < fields.Length; i++)
                {
                    field = fields[i];
                    attributes = Attribute.GetCustomAttributes(field, typeof(ColumnAttributes), false);
                    structureInfo[i, 0] = field;
                    structureInfo[i, 1] = attributes;
                }
            }
            catch (Exception) { throw; }
            return structureInfo;
        }
        #endregion

        #region Set Fields
        public void SetFields(object[,] structureInfo, DataRow row)
        {

            PropertyInfo field;
            Attribute[] attributes;
            try
            {
                for (int i = 0; i <= structureInfo.GetUpperBound(0); i++)
                {

                    field = (PropertyInfo)structureInfo[i, 0];
                    attributes = (Attribute[])structureInfo[i, 1];
                    foreach (Attribute attribute in attributes)
                    {
                        ColumnAttributes columnAttributeName = (ColumnAttributes)attribute;
                        if (!row.Table.Columns.Contains(columnAttributeName.ColumnName)) { continue; }
                        if (row[columnAttributeName.ColumnName] == System.DBNull.Value) { continue; }
                        if (field.PropertyType.Name == "Guid")
                            field.SetValue(this, new Guid(row[columnAttributeName.ColumnName].ToString()), null);
                        else
                        field.SetValue(this, row[columnAttributeName.ColumnName], null);


                        break;
                    }

                }
            }
            catch (Exception ex ) { throw ex ; }
            return;
        }
        #endregion

        #region Serialization
        public string ToXml()
        {

            StringWriter output = new StringWriter(new StringBuilder());
            string returnValue = "";
            try
            {
                XmlSerializer s = new XmlSerializer(this.GetType());
                s.Serialize(output, this);
                returnValue = output.ToString().Replace("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"", "");
                returnValue = returnValue.Replace("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
                returnValue = returnValue.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
            }
            catch (Exception) { throw; }
            return returnValue;
        }
        #endregion

        #region Validate Required Properties
        ///<summary> 
        /// Validate required values in order to 
        /// save a record to the UserGroup database table. 
        /// </summary> 
        public bool ValidateRequiredProperties(object[,] properties,
                                               List<string> returnMessages)
        {
            bool returnValue = true;
            PropertyInfo property;
            Attribute[] attributes;
            ColumnAttributes columnAttribute = null;

            try
            {

                if (properties == null)
                {
                    throw new Exception("Please pass in the results of this.GetFields().");
                }

                if (returnMessages != null)
                {
                    returnMessages.Clear();
                }

                for (int i = 0; i <= properties.GetUpperBound(0); i++)
                {

                    property = (PropertyInfo)properties[i, 0];
                    attributes = (Attribute[])properties[i, 1];

                    foreach (Attribute attribute in attributes)
                    {

                        columnAttribute = (ColumnAttributes)attribute;

                        if (!columnAttribute.IsRequired)
                        {
                            continue;
                        }

                        //    Debug.WriteLine(columnAttribute.ColumnName); 
                        //     Debug.WriteLine(property.GetValue(this,null)); 

                        if (!this.ValidateRequiredPropertyInfo(columnAttribute,property))
                        {

                            returnValue = false;

                            if (returnMessages != null)
                            {
                                returnMessages.Add(columnAttribute.ColumnName + " is required.");
                            }
                        }

                    }

                }
            }
            catch (Exception)
            {
                throw;
            }
            return returnValue;
        }
        #endregion

        #region Validate Required Properties
        /// <summary> 
        /// Validate required values associated with this class.
        /// </summary> 
        public bool ValidateRequiredProperties(object[,] properties)
        {
            List<string> returnMessages = null;

            try
            {
                return ValidateRequiredProperties(properties,
                                                  returnMessages);
            }
            catch (Exception) { throw; }
        }
        #endregion

        #region Validate Required Property Info
        /// <summary> 
        /// Validate required value in the given property.
        /// </summary> 
        public bool ValidateRequiredPropertyInfo(ColumnAttributes columnAttribute,
                                                 PropertyInfo property)
        {
            try
            {
                switch (columnAttribute.PropertyType.ToLower())
                {

                    case "int":

                        if ((int)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "Int16":

                        if ((Int16)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "Int32":

                        if ((Int32)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "Int64":

                        if ((Int64)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "uint":

                        if ((uint)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "uInt16":

                        if ((UInt16)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "uInt32":

                        if ((UInt32)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "uInt64":

                        if ((UInt64)property.GetValue(this,
                                              null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "double?":

                        if ((double?)property.GetValue(this,
                                                      null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "float?":

                        if ((float?)property.GetValue(this,
                                                     null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "single?":

                        if ((Single?)property.GetValue(this,
                                                     null) == 0)
                        {
                            return false;
                        }

                        break;

                    case "string":

                        if ((string)property.GetValue(this,
                                                      null) == String.Empty)
                        {
                            return false;
                        }

                        break;

                    case "guid":

                        if ((Guid)property.GetValue(this,
                                                    null) == Guid.Empty)
                        {
                            return false;
                        }

                        break;


                    default:

                        if (property.GetValue(this,
                                              null) == null)
                        {
                            return false;
                        }

                        break;
                }
            }
            catch (Exception) { throw; }
            return true;
        }
        #endregion

        #region Get Set Methods for String Properties

        protected string Getbigint_s(Int64 p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setbigint_s(string value, ref Int64  p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                Int64 conv = -1;
                if (!Int64.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getbinary_s(byte[] p)
        {
            if (p == null) return string.Empty;
            Encoding unicode = Encoding.Unicode;
            char[] unicodeChars = new char[unicode.GetCharCount(p, 0, p.Length)];
            unicode.GetChars(p, 0, p.Length, unicodeChars, 0);
            return new string(unicodeChars);
        }
        protected void Setbinary_s(string value, ref byte[] p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else
            {
                Encoding unicode = Encoding.Unicode;
                p = unicode.GetBytes(value);
            }
        }

        protected string Getbit_s(bool p) { return p.ToString(); }
        protected void Setbit_s(string value, ref bool p)
        {
            if (string.IsNullOrEmpty(value)) p = false;
            else
            {
                bool conv = false;
                if (!bool.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getchar_s(string p) { return p.ToString(); }
        protected void Setchar_s(string value, ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        protected string Getdate_s(DateTime p) { return p == new DateTime() ? string.Empty : p.ToString(); }
        protected void Setdate_s(string value, ref DateTime p)
        {
            if (string.IsNullOrEmpty(value)) p = new DateTime();
            else
            {
                DateTime conv = new DateTime();
                if (!DateTime.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getdatetime_s(DateTime p) { return p == new DateTime() ? string.Empty : p.ToString(); }
        protected void Setdatetime_s(string value, ref DateTime p)
        {
            if (string.IsNullOrEmpty(value)) p = new DateTime();
            else
            {
                DateTime conv = new DateTime();
                if (!DateTime.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getdatetime2_s(DateTime p) { return p == new DateTime() ? string.Empty : p.ToString(); }
        protected void Setdatetime2_s(string value, ref DateTime p)
        {
            if (string.IsNullOrEmpty(value)) p = new DateTime();
            else
            {
                DateTime conv = new DateTime();
                if (!DateTime.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getdatetimeoffset_s(DateTimeOffset p) { return p == new DateTime() ? string.Empty : p.ToString(); }
        protected void Setdatetimeoffset_s(string value, ref DateTimeOffset p)
        {
            if (string.IsNullOrEmpty(value)) p = new DateTimeOffset();
            else
            {
                DateTimeOffset conv = new DateTimeOffset();
                if (!DateTimeOffset.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getdecimal_s(decimal p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setdecimal_s(string value, ref decimal p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                decimal conv = -1;
                if (!decimal.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getfloat_s(double p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setfloat_s(string value, ref double p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                double conv = -1;
                if (!double.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getimage_s(byte[] p)
        {
            if (p == null) return string.Empty;
            Encoding unicode = Encoding.Unicode;
            char[] unicodeChars = new char[unicode.GetCharCount(p, 0, p.Length)];
            unicode.GetChars(p, 0, p.Length, unicodeChars, 0);
            return new string(unicodeChars);
        }
        protected void Setimage_s(string value, ref byte[] p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else
            {
                Encoding unicode = Encoding.Unicode;
                p = unicode.GetBytes(value);
            }
        }

        protected string Getint_s(int p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setint_s(string value, ref int p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                int conv = -1;
                if (!int.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getmoney_s(decimal p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setmoney_s(string value, ref decimal p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                decimal conv = -1;
                if (!decimal.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getnchar_s(string p) { return p.ToString(); }
        protected void Setnchar_s(string value, ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        protected string Getntext_s(string p) { return p.ToString(); }
        protected void Setntext_s(string value, ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        protected string Getnumeric_s(decimal p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setnumeric_s(string value, ref decimal p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                decimal conv = -1;
                if (!decimal.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getnvarchar_s(string p) { return p.ToString(); }
        protected void Setnvarchar_s(string value, ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        protected string Getreal_s(Single p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setreal_s(string value, ref Single p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                Single conv = -1;
                if (!Single.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getsmalldatetime_s(DateTime p) { return p == new DateTime() ? string.Empty : p.ToString(); }
        protected void Setsmalldatetime_s(string value, ref DateTime p)
        {
            if (string.IsNullOrEmpty(value)) p = new DateTime();
            else
            {
                DateTime conv = new DateTime();
                if (!DateTime.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getsmallint_s(Int16 p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setsmallint_s(string value, ref Int16 p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                Int16 conv = -1;
                if (!Int16.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getsmallmoney_s(decimal p) { return p == -1 ? string.Empty : p.ToString(); }
        protected void Setsmallmoney_s(string value, ref decimal p)
        {
            if (string.IsNullOrEmpty(value)) p = -1;
            else
            {
                decimal conv = -1;
                if (!decimal.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getsql_variant_s(object p) { return p == null ? string.Empty : p.ToString(); }
        protected void Setsql_variant_s(string value, ref object p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else { p = value; }
        }

        protected string Gettext_s(string p) { return p.ToString(); }
        protected void Settext_s(string value, ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        protected string Gettime_s(TimeSpan p) { return p == new TimeSpan() ? string.Empty : p.ToString(); }
        protected void Settime_s(string value, ref TimeSpan p)
        {
            if (string.IsNullOrEmpty(value)) p = new TimeSpan();
            else
            {
                TimeSpan conv = new TimeSpan();
                if (!TimeSpan.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Gettimestamp_s(DateTime p) { return p == new DateTime() ? string.Empty : p.ToString(); }
        protected void Settimestamp_s(string value, ref DateTime p)
        {
            if (string.IsNullOrEmpty(value)) p = new DateTime();
            else
            {
                DateTime conv = new DateTime();
                if (!DateTime.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Gettinyint_s(byte p) { return p == 0 ? string.Empty : p.ToString(); }
        protected void Settinyint_s(string value,  ref byte p)
        {
            if (string.IsNullOrEmpty(value)) p = 0;
            else
            {
                byte conv = 0;
                if (!byte.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getuniqueidentifier_s(Guid p) { return p == Guid.Empty ? string.Empty : p.ToString(); }
        protected void Setuniqueidentifier_s(string value,  ref Guid p)
        {
            if (string.IsNullOrEmpty(value)) p = Guid.Empty;
            else
            {
                Guid conv = Guid.Empty;
                if (!Guid.TryParse(value, out conv)) throw new Exception("Hatalı dönüşüm");
                p = conv;
            }
        }

        protected string Getvarbinary_s(byte[] p)
        {
            if (p == null) return string.Empty;
            Encoding unicode = Encoding.Unicode;
            char[] unicodeChars = new char[unicode.GetCharCount(p, 0, p.Length)];
            unicode.GetChars(p, 0, p.Length, unicodeChars, 0);
            return new string(unicodeChars);
        }
        protected void Setvarbinary_s(string value,  ref byte[] p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else
            {
                Encoding unicode = Encoding.Unicode;
                p = unicode.GetBytes(value);
            }
        }

        protected string Getvarchar_s(string p) { return p.ToString(); }
        protected void Setvarchar_s(string value,  ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        protected string Getxml_s(string p) { return p.ToString(); }
        protected void Setxml_s(string value,  ref string p)
        {
            if (string.IsNullOrEmpty(value)) p = null;
            else p = value;
        }

        #endregion

    }
}
